/***************************************************************************
 *   Copyright (C) 2009 by Zheng Yonglei
 *   zhengyonglei@gmail.com   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#ifndef __WORD_H
#define __WORD_H

#include <iostream>
#include <iomanip>
#include <sstream>
#include <fstream>
#include <vector>
#include <string>
#include <map>
#include <cmath>

#include <QString>
 #include <QDate>

#include "Logger.h"
#include "types.h"
#include "WordManager.h"
#include "Options.h"

using namespace std;

#define HISTORY_SEPARATOR "|"
#define MEM_LEV_YN_RATE 		1
#define MEM_LEV_MEG_RATE		10
#define MEM_LEV_MEX_RATE 		100
#define MEM_LEV_SP_RATE 		1000

#define MEM_LEV_YN_CEIL_MAX	 	5 		//the max ceiling of memory_level::yes/no_method
#define MEM_LEV_MEG_CEIL_MAX 	5		//the max ceiling of memory_level::multi-eng_method
#define MEM_LEV_MEX_CEIL_MAX	5		//the max ceiling of memory_level::multi-exp_method
#define MEM_LEV_SP_CEIL_MAX	 	5		//the max ceiling of memory_level::spell_method

class ReciteTestPolity
{
public:
	static int getYesNoTestFinishCount(int impLevel);
	static int getMultiEngTestFinishCount(int impLevel);
	static int getMultiExpTestFinishCount(int impLevel);
	static int getSpellTestFinishCount(int impLevel);

};

class ReciteDateHistory //include recite date and remember forget history
{
private:
	QDate mReciteDate;
	vector<bool> mRemForHistory;
	QString mDateString;
	QString mRemForHistoryString;
	QString mReciteDateString;

	int mRememberCount;
	int mForgetCount;

public:
	ReciteDateHistory();
	ReciteDateHistory(QDate date, QString remForHistoryString);

	void remember();
	void forget();

	//recite history encode/decode methods
	QString encodeReciteHistory();
	void decodeReciteHistory();

	//set functions
	void setRememberCount(int rememberCounterArg){mRememberCount=rememberCounterArg;}
	void setForgetCount(int forgetCounterArg){mForgetCount=forgetCounterArg;}

	//get functions
	vector<bool>& getRemForHistory(){return mRemForHistory;}
	int getInterval();
	int getRememberCount(){return mRememberCount;}
	int getForgetCount(){return mForgetCount;}
	int getTotalReciteCount(){return (mRememberCount + mForgetCount);}
	QString getDateString(){return mDateString;}
	QString getRemForHistoryString(){return mRemForHistoryString;}
	QString getReciteDateHistoryString(){return mReciteDateString;}
};

class Word
{
protected:
	//basic information
	int mID;
	QString mEnglish;
	QString mSoundMark;
	map<QString, map<QString, QString> > mExplanations; // map<dictName, map<key, article> >
	//reciting information
	bool mIsActive;//only active word will be chosen to recite
	bool mIsFrozen;
	bool mPassLastTest;
	int mFrozenRemainCycle;
	int mDifficultyLevel;
	int mImportanceLevel;
	int mMemoryLevel;
	int mMemoryLevelDelta;
	WordStatus mStatus;
	map<QDate, ReciteDateHistory> mReciteHistory;

public:
	Word();
	Word(int id);

	void setWordHistory();

	void remember(); //modify memory level.
	void forget(); //modify memory level
	void refineMemoryLevel(); //to refine the memory level according to your performance
	void refineDifficultyLevel();
	void setFrozenRemainCycle();
	TestMethod selectTestMethod();

	//get functions
	int getID(){return mID;}
	void setID(int id){mID = id;}

	int getExplanationCount(){return mExplanations.size();}
	int getTotalReciteCount();
	float getGrossPassRate();
	int getFrozenRemainCycle(){return mFrozenRemainCycle;}

	int getMemoryLevel(){return mMemoryLevel;}
	int getMemoryLevel(TestMethod testMethod);
	int getMemoryLevelDelta(){return mMemoryLevelDelta;}

	QString getExplanation(QString dictName);
	map<QString, QString>& getExplanationMap(QString dictName);
	map<QString, map<QString, QString> >& getExplanations(){return mExplanations;}
	QString getRedBibleExp();
	QString getEnglish(){return mEnglish;}
	QString getSoundMark(){return mSoundMark;}
	QString getReciteDateHistoryString();
	QStringList getReciteDateString();

	void checkIsFinished();
	//bool isFinished();
	bool isFrozen(){return mIsFrozen;}
	WordStatus getWordStatus(){return mStatus;}
	QString getWordStatusString();
	int getDifficultyLevel(){return mDifficultyLevel;}
	bool passLastTest(){return mPassLastTest;}
	int getImportanceLevel(){return mImportanceLevel;}

	//set functions
	void setRedBibleExp(QString Explanation);
	void clearExplanations(){mExplanations.clear();}

	void setMemoryLevel(int memoryLevelArg){mMemoryLevel=memoryLevelArg;}
	void setMemoryLevelDelta(int memoryLevelDeltaArg){ mMemoryLevelDelta=memoryLevelDeltaArg;}
	void setEnglish(QString English){mEnglish=English;}
	void setSoundMark(QString soundMark){mSoundMark = soundMark;}
	void setDifficultyLevel(int level){mDifficultyLevel = level;}
	void setImportanceLevel(int level){mImportanceLevel = level;}
	void setFrozenRemainCycle(int frozenRemainCycleArg){mFrozenRemainCycle = frozenRemainCycleArg;}
	void setIsFrozen(bool frozenArg){mIsFrozen = frozenArg;}
	void setWordStatus(int statusArg);
	void setReciteDateHistory(QString dateHistoryArg);
};

#endif //__WORD_H
